<template>
  <el-select
    ref="mySelect"
    :value="valueFilter(value)"
    :placeholder="$attrs['placeholder']"
    :multiple="$attrs['show-checkbox']"
    :filterable="$attrs['filterable']"
    :clearable="$attrs['clearable']"
    :collapse-tags="$attrs['collapse-tags']"
    :filter-method="remoteMethod"
    @change="selectChange"
    @clear="selectClear">
    <template slot="empty" >
      <div class="selecTree">
        <el-tree 
          ref="myTree"
          highlight-current
          :node-key="props.value"
          :data="data"
          :props="props"
          :check-on-click-node="$attrs['check-on-click-node']"
          :expand-on-click-node="$attrs['expand-on-click-node']"
          :show-checkbox= "$attrs['show-checkbox']"
          :defaultExpandAll="$attrs['defaultExpandAll']"
          :filter-node-method="filterNode" 
          @node-click="handleNodeClick"
          @check-change="handleCheckChange">
          <template slot-scope="{ node, data }">
            <slot :node="node" :data="data">
              <span class="slotSpan">
                <span>
                  {{ data[props.label] }}
                  <b v-if="$attrs['show-count'] != undefined && data[props.children]">（{{ data[props.children].length }}）</b>
                </span>
              </span>
            </slot>
          </template>
        </el-tree>
      </div>
    </template>
  </el-select>
</template>
<script>
export default {
    name: '',
    props: {
      value: {
          type: undefined,
          default: null,
      },
      data: {
        type: Array,
        default: () => {
          return []
        }
      },
      props: {
        type: Object,
        default: () => {
          return {
            children: 'children',
            label: 'label',
            value: 'value'
          }
        }
      }
    },
    data() {
      return{
         
      }
    },
    watch: {
    },
    methods: {
      valueFilter(val) {
        if (this.$attrs['show-checkbox'] === undefined) {
            let [res] =  this.recurrenceQuery(this.data, this.props.value, val)
            return res?.[this.props.label] || ''
        } else {
            if (!val?.length) {
              return []
            }
            let res = val.map(item => {
              let [newItem] = this.recurrenceQuery(this.data, this.props.value, item)
              return newItem?.[this.props.label] || ''
            })
            if (!res?.length) {
              return []
            }
            res = res.filter(item => item)
            return res
        }
      },
      recurrenceQuery(list, key, value) {
        if (!list || !key || !value) {
          return []
        }
        let queryData = []
        for (const item of list) {
          if (item[key] == value) {
            queryData.push(item)
            break
          }else{
            if (item[this.props.children] && item[this.props.children].length) {
              queryData.push(...this.recurrenceQuery(item[this.props.children], key, value))
            }
          }
        }
        return queryData
      },
      // 多选
      handleCheckChange(data, checked, childrenChecked) {
        let checkList = this.$refs.myTree.getCheckedNodes()
        let setList = null
        if (checkList.length) {
            setList = checkList.map(item => item[this.props.value])
        } 
        this.$emit('input', setList);
        // 共三个参数，依次为：传递给 data 属性的数组中该节点所对应的对象、节点本身是否被选中、节点的子树中是否有被选中的节点
        this.$emit('change', {multiple:true,data:data,checked:checked,childrenChecked:childrenChecked})
      },
      // 单选事件
      handleNodeClick(data) { 
        if (this.$attrs['show-checkbox'] === undefined) {
          this.$emit('input', data[this.props.value])
          this.$refs.mySelect.blur()
        } else {
          if (data[this.props.children] && data[this.props.children]?.length) {
            return false
          }
        }
        this.$emit('change',{multiple:false,data:data,checked:true,childrenChecked:((data.children && data.children.leng > 0)?true:false)})
      },
      remoteMethod(query) {
        this.$refs.myTree.filter(query)
      },
      // 筛选
      filterNode(value, data) {
        if (!value) return true
        return data[this.props.label].indexOf(value) !== -1
      },
      resetfilter() {
        this.filterValue=null
        this.$refs.myTree.filter(null)
      },
      selectChange(current) { 
        if (this.$attrs['show-checkbox'] !== undefined) {
          this.$refs.myTree.setCheckedKeys([])
          if(current){
            let currentKeys = current.map(value => {
              let item = this.recurrenceQuery(this.data, this.props.label, value)
              return item[0][this.props.value]
            })
            currentKeys.forEach(item => { 
              this.$nextTick(() => {
                this.$refs.myTree.setChecked(item, true, false)
              })
            })
            this.$emit('input', current)
          }
        }
      },
      selectClear() { 
        if (this.$attrs['show-checkbox'] === undefined) {
          this.$refs.myTree.setCurrentKey(null) 
          this.$emit('input', '')
          this.$emit('change',{multiple:false,data:null,checked:false,childrenChecked:false})
        } else {
          this.$refs.myTree.setCheckedKeys([])
          this.$emit('input', [])
        }
        // this.remoteMethod('');
      }
    }
}
</script>
<style>
.selecTree {
    max-height: 50vh;
    overflow: auto;
    padding: 5px;
}
.el-select {
    width: 100%;
}
.slotSpan {
    font-size: 14px;
    b {
        font-weight: normal;
        font-size: 12px;
        color: #999;
    }
}
.selecTree ::v-deep .el-tree-node__content {
    font-size: 14px;
}
</style>


<!-- <template>
    <el-select
      ref="selectRef"
      :placeholder="placeholder"
      :clearable = "clearable"
      :filterable="filterableFor || remoteFor"
      :remote="filterableFor || remoteFor"
      :remote-method="selectRemoteMethod"
      v-model="currentLabel"
      @visible-change="handleVisibleChange"
      @clear="handleClear">
      <el-option
        style="height: 100%; padding: 0"
        value=""
        v-loading="loading"
        element-loading-text="加载中..."
        element-loading-spinner="el-icon-loading">
        <el-tree 
          ref="treeRef"
          :data="dataOfTree"
          :node-key="defaultProps.value"
          :props="defaultProps"
          highlight-current
          :default-expand-all="defaultexpandall"
          :current-node-key="selectedNode.value"
          :expand-on-click-node="expandonclicknode"
          :filter-node-method="filterNode"
          @node-click="handleNodeClicked"
          @check-change="handleCheckChange">
        </el-tree>
      </el-option>
    </el-select>
  </template>
  <script>
   
  export default {
    name: 'TreeSelect',
    components: {},
    model: {
      prop: 'inputValue',
      event: 'myInputEvent'
    },
    props: {
      placeholder: {
        type: String,
        default: "请选择"
      },
      // 默认选中值
      defaultValue: {
        type: Number
      },
      expandonclicknode: {
        type: Boolean,
        default: false
      },
      defaultexpandall: {
        type: Boolean,
        default: false
      },
      clearable: {
        type: Boolean,
        default: false
      },
      multiple: {
        type: Boolean,
        default: false
      },
      // 是否支持搜索，本地搜索，与远程搜索配置互斥。
      filterable: {
        type: Boolean,
        default: false
      },
      // 是否远程搜索，要设置远程搜索方法
      remote: {
        type: Boolean,
        default: false
      },
      // 远程方法
      remoteMethod: {
        type: Function
      },
      treeOptions: {
        type: Array,
        default: () => {
          return []
        }
      },
      defaultProps: {
        type: Object,
        default: () => {
          return {
            children: 'children',
            label: 'label',
            value: 'value'
          }
        }
      }
    },
    watch: {
      treeOptions: {
        handler(newValue) { 
          this.loading = false
          this.dataOfTree = JSON.parse(JSON.stringify(newValue))
          this.dataSource = JSON.parse(JSON.stringify(newValue))
        },
        deep: true,
        immediate: false
      },
      defaultValue: {
        handler(newValue) {
          if(newValue){
            this.selectedNode = {}
            this.currentLabel = undefined
            this.currentValue = newValue
            this.$nextTick(() => {
              // 过滤方式是通过value还是label;
              this.isFilterWithValue = true
              if (this.dataOfTree) {
                this.$refs.treeRef.filter(newValue)
              }
            })
          }
        },
        deep: true,
        immediate: true
      }
    },
    computed: {
      // 是否支持搜索，本地搜索，与远程搜索配置互斥。
      filterableFor() {
        return this.remote ? false : this.filterable
      },
      remoteFor() {
        return this.filterable ? false : this.remote
      }
    },
    data() {
      return {
        selectedNode: {},
        loading: false,
        currentValue: undefined,
        currentLabel: undefined,
        dataOfTree: [],
        currentValues: [],
        currentLabels: [],
      }
    },
    created() {
      this.dataOfTree = JSON.parse(JSON.stringify(this.treeOptions))
      // 保留源数据；
      this.dataSource = JSON.parse(JSON.stringify(this.treeOptions))
    },
    mounted() {
    },
    methods: {
      selectRemoteMethod(val) {
        this.isFilterWithValue = false
        if (this.filterableFor) {
          // 本地过滤
          this.$refs.treeRef.filter(val)
        } else if (this.remoteFor) {
          // 远程搜索
          this.loading = true
          this.remoteMethod(val)
        }
      },
      handleClear() {
        // 如果内容被清空
        this.selectedNode = {}
        this.currentLabel = undefined
        this.currentValue = undefined
        const result = this.buildEmptyResult()
        this.$emit('myInputEvent', result.value)
        this.$emit('onNodeSelectEvent', result)
      },
      handleVisibleChange(visible) {
        if (!visible) {
          // 先移除所有数据；
          this.dataOfTree.splice(0)
          // 恢复原来的所有数据；
          this.dataOfTree.splice(0, 0, ...this.dataSource)
          // 本地过滤
          this.$refs.treeRef.filter('')
        }
      },
      filterNode(value, data) {
        if (!value) {
          return data
        }
        if (this.isFilterWithValue) {
          if (data[this.defaultProps.value] === value) {
            this.selectedNode = data
            this.currentLabel = data[this.defaultProps.label]
            this.$refs.treeRef.setCurrentKey(this.selectedNode[this.defaultProps.value])
            const result = this.buildResultByNodeData(data)
            this.$emit('myInputEvent', result.value)
          }
        } else {
          return data[this.defaultProps.label].indexOf(value) !== -1
        }
        return data
      },
      closeSelect() {
        this.$refs.selectRef.blur()
      },
      /**
       * @param data
       * @param node
       * @param comp
       */
      handleNodeClicked(data, node, comp) { 
        this.selectedNode = data 
        this.currentLabel = data[this.defaultProps.label] 
        this.currentValue = data[this.defaultProps.value]
        const result = this.buildResultByNodeData(data)
        this.$emit('myInputEvent', result.value)
        this.$emit('onNodeSelectEvent', result)
        this.closeSelect()
      },
      handleCheckChange(data, checked, indeterminate){ 
        console.log("handleCheckChange", data)
      },
      buildResultByNodeData(data) {
        return {
          label: data[this.defaultProps.label],
          value: data[this.defaultProps.value],
          meta: data
        }
      },
      buildEmptyResult() {
        return {
          label: undefined,
          value: undefined,
          meta: undefined
        }
      }
    }
  }
  </script>
  <style lang='scss' scoped>
  </style> -->